#include <muduo/net/TcpClient.h>

#include <muduo/base/Logging.h>
#include <muduo/base/Thread.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/InetAddress.h>

#include <boost/bind.hpp>

#include <utility>

#include <stdio.h>
#include <unistd.h>
#include "pthread.h"

using namespace muduo;
using namespace muduo::net;

class DiscardClient : boost::noncopyable {
public:
    DiscardClient(EventLoop *loop, const InetAddress &listenAddr, int size)
            : loop_(loop),
              client_(loop, listenAddr, "DiscardClient"),
              message_(size, 'H') {

        client_.enableRetry();
//        LOG_DEBUG<<"retry connected:"<<client_.retry();


        client_.setConnectionCallback(
                boost::bind(&DiscardClient::onConnection, this, _1));
        client_.setMessageCallback(
                boost::bind(&DiscardClient::onMessage, this, _1, _2, _3));
        client_.setWriteCompleteCallback(
                boost::bind(&DiscardClient::onWriteComplete, this, _1));

    }

    void connect() {
        client_.connect();
    }

private:
    /**
     * TcpConnection
     */
    void onConnection(const TcpConnectionPtr &conn) {
        LOG_TRACE << conn->localAddress().toIpPort() << " -> "
                  << conn->peerAddress().toIpPort() << " is "
                  << (conn->connected() ? "UP" : "DOWN");

        if (conn->connected()) {
            conn->setTcpNoDelay(true);
            conn->send(message_);
        } else {
            LOG_DEBUG << "connection down,try to rertry connectd";
        }
    }

    void onMessage(const TcpConnectionPtr &conn, Buffer *buf, Timestamp time) {
        buf->retrieveAll();
    }

    /**
     *
     */
    void onWriteComplete(const TcpConnectionPtr &conn) {
        // LOG_INFO << "write complete " << message_.size();
        conn->send(message_);
    }


    EventLoop *loop_;
    TcpClient client_;
    string message_;

};


void test_bind(int value) {

    LOG_DEBUG << "测试 test bind!!!! value:" << value;

}

int main(int argc, char *argv[]) {

    Logger::setLogLevel(Logger::DEBUG);

    LOG_INFO << "pid = " << getpid() << ", tid = " << CurrentThread::tid();
    if (argc > 1) {
        EventLoop loop;
        InetAddress serverAddr(argv[1], 2009);

        int size = 256;
        if (argc > 2) {
            size = atoi(argv[2]);
        }

        DiscardClient client(&loop, serverAddr, size);

        const string thread_name = "muduo客户端连接线程";
        //boost::function<void()> ThreadFunc
        muduo::Thread::ThreadFunc threadFunc = boost::bind(&DiscardClient::connect, &client);//传递指针
        //threadFunc()----> client.connect()
        Thread thread(threadFunc, thread_name);
        LOG_DEBUG << " thread pid:\n" << thread.tid()
                  << "thread name:\n" << thread.name() << " is started:" << ((thread.started() == 1));
        thread.start();
        thread.join();

        // test bind
        boost::function<void(int)> t_func = boost::bind(&test_bind, _1);// 函数地址
        t_func(1009098);

        loop.loop();
    }
    else {
        printf("Usage: %s host_ip [msg_size]\n", argv[0]);
    }
}

